package internal

import (
	"fmt"
	"log"
	"net/url"
	"strconv"
	"time"

	"gitee.com/go-errors/errors"
	"gitee.com/go-wena/env"

	"gorm.io/gorm"
	"gorm.io/gorm/schema"
)

func New(dsn string) (db *gorm.DB) {
	d, err := func() (gorm.Dialector, error) {
		uri, err := url.Parse(dsn)
		if err != nil {
			return nil, err
		}

		var (
			driver      = uri.Scheme
			host        = uri.Hostname()
			port, _     = strconv.Atoi(uri.Port())
			username    = uri.User.Username()
			password, _ = uri.User.Password()
			path        = uri.Path
			qs          = uri.RawQuery
		)

		if qs != "" && qs[0] != '?' {
			qs = "?" + qs
		}

		switch driver {
		case "sqlite":
			return dialSqlite(fmt.Sprintf("%s%s", path, qs)), nil
		case "mysql":
			if port == 0 {
				port = 3306
			}
			return dialMysql(fmt.Sprintf("%s:%s@tcp(%s:%d)/%s%s", username, password, host, port, path, qs)), nil
		case "postgres", "postgresql":
			//if port == 0 {
			//	port = 5432
			//}
			//return dialPostgres(fmt.Sprintf("postgres://%s:%s@%s:%d/%s%s", username, password, host, port, path, qs)), nil
			return dialPostgres(dsn), nil
		default:
			return nil, errors.Errorf("unknown dsn: %s", dsn)
		}
	}()

	if err != nil {
		log.Printf("sql: %v\n", err)
	}

	var locCST = time.FixedZone("CST", 3600*8)
	db, err = gorm.Open(d, &gorm.Config{
		SkipDefaultTransaction: env.GetBool("sql.skip_default_transaction", true),
		NamingStrategy: schema.NamingStrategy{
			SingularTable: env.GetBool("sql.singular_table", true),
			NoLowerCase:   env.GetBool("sql.no_lower_case", true),
		},
		NowFunc:                                  func() time.Time { return time.Now().In(locCST) },
		PrepareStmt:                              env.GetBool("sql.prepare_stmt", true),
		DisableAutomaticPing:                     env.GetBool("sql.disable_automatic_ping", true),
		QueryFields:                              env.GetBool("sql.query_fields", true),
		CreateBatchSize:                          int(env.GetInt("sql.create_batch_size", 100)),
		DisableForeignKeyConstraintWhenMigrating: env.GetBool("sql.disable_foreign_key_constraint_when_migrating", true),
	})

	if err != nil {
		return &gorm.DB{Error: errors.Errorf("sql: open database error: dsn: %q: %v\n", dsn, err)}
	}

	if env.GetBool("sql.debug") {
		db = db.Debug()
	}

	return db
}
